package TpFinal;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Semaforo extends Thread {

	private String identificador;
	private boolean condicionDeCruce;
	private Semaphore mutexCondicion = new Semaphore(1);
	private Lock bloqueDelSemaforo = new ReentrantLock();
	private Condition esperandoEnSemaforo = bloqueDelSemaforo.newCondition();
	
	public Semaforo(String nombre) {
		this.identificador = nombre;
		this.condicionDeCruce = false;
	}

	/**
	 * dependiendo de la condicion de cruce si no puede cruzar bloquea al auto 
	 * en una variable de condicion de un monitor 
	 * si puede cruzar simplemente pasa
	 */
	public void puedeCruzar(Auto auto) {
		bloqueDelSemaforo.lock();
		try {
			while(!this.condicionDeCruce){
				System.out.println(auto.getIdentificador()+" espera en "+this.identificador);
				esperandoEnSemaforo.await();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			bloqueDelSemaforo.unlock();
		}
	}
	
	/**
	 * en este metodo se cambia la variable que 
	 * condiciona el cruce a true y se libera a los autos que podrian estar
	 * bloqueados en la variable de condicion del monitor del semaforo
	 * que solo puede ser uno por vez 
	 */
	private void cambiarAVerde() {
		bloqueDelSemaforo.lock();
		mutexCondicion.acquireUninterruptibly();
		this.condicionDeCruce = true;
		System.out.println(this.identificador + " VERDE");
		mutexCondicion.release();
		esperandoEnSemaforo.signal();
		bloqueDelSemaforo.unlock();
	}

	/**
	 * se cambia la variable de condicion de cruce a false
	 */
	private void cambiarARojo() {
		mutexCondicion.acquireUninterruptibly();
		this.condicionDeCruce = false;
		System.out.println(this.identificador + " ROJO");
		mutexCondicion.release();
	}
	
	/**
	 * el semaforo se comunica con un servidor y va cambiando de verde a rojo 
	 * quedando un tiempo fijo en verde
	 * escucha al servidor para ponerse en verde y le comunica al servidor
	 * cuando se puso en rojo
	 */
	public void run() {
		Socket cliente;
		try {

			cliente = new Socket("localhost", 4500);
			BufferedReader read = new BufferedReader(new InputStreamReader(
					cliente.getInputStream()));
			PrintStream output = new PrintStream(cliente.getOutputStream());
			System.out.println(this.identificador + " ROJO");
			while (true) {
				read.readLine();
				this.cambiarAVerde();
				Thread.sleep(6000);
				this.cambiarARojo();
				output.println("rojo");
			}
			
		} catch (Exception e) {
			System.err.println("error en el cliente "+this.getIdentificador());
		}
	}

	public String getIdentificador() {
		return identificador;
	}

	public void setIdentificador(String identificador) {
		this.identificador = identificador;
	}
}
